import { Button, NavBar, Form, Input, Toast } from "antd-mobile"
import styles from "./index.module.scss" // css模块化 避免样式的冲突
import { login } from "@/store/actions/login"
import { useDispatch } from "react-redux"
import { useHistory, useLocation } from "react-router-dom"
import { useRef, useState, useEffect } from "react"
import type { LoginForm } from "@/types/data"
import type { AxiosError } from "axios" // 引入axios错误对象类型
import type { InputRef } from "antd-mobile/es/components/input"
import { sendCode } from "@/store/actions/login"
const Login = () => {
  const [form] = Form.useForm() // 直接使用useForm得到一个form实例对象
  const dispatch = useDispatch() // 得到一个dispatch对象
  const history = useHistory() // 此时可以用 因为当前是一个react函数组件
  const mobileRef = useRef<InputRef>(null) // 创建一个ref 传入泛型类型
  const timeRef = useRef(-1) // 将定时器的标识赋值给ref current属性
  const location = useLocation<{ from: string } | undefined>() // 获取当前路由信息

  // 定义一个状态管理验证码的剩余时间
  const [timeLeft, setTimeLeft] = useState(0)
  //  定义一个表单提交事件, 此时一定是表单校验通过 mobile/code
  const onFinish = async (values: LoginForm) => {
    // login()
    try {
      await dispatch(login(values)) // 触发登录的action  thunk
      // 此时表示分发action成功 登录成功
      // 跳转到主页
      Toast.show({
        content: "登录成功",
        duration: 500,
        afterClose: () => {
          // 登录页，直接到登录页 登录
          // 去了一个需要权限的页面 转发到登录
          if (location.state) {
            history.replace(location.state.from)
            return
          }
          history.replace("/home/index") // 调到主页
        },
      })
    } catch (error) {
      // 此时需要 提示异常 需要知道错误是什么
      // 要获取错误的提示信息
      // 实际error是有内容的
      // 此时需要将error对象转化成一个类型
      const e = error as AxiosError<{ message: string }> // 类型断言
      Toast.show({
        content: e.response?.data?.message,
      })
    }
  }

  /**
   * 点击发送验证码
   * **/
  const onSendCode = async () => {
    // 调用接口 拿到手机号
    const mobile = (form.getFieldValue("mobile") || "") as string // 保证mobile是一个字符串
    // 判断当前的手机号是否满足了校验的要求，否则不能发送
    const isError = !!form.getFieldError("mobile").length as boolean // 进入输入框 会有错误 没有进入输入框 没有错误
    if (isError || mobile.trim() === "") {
      // 此时表示有错误 不能发送 将光标定位到手机输入框中
      mobileRef.current?.focus() // 定位光标到input输入框
      return // 直接返回 因为手机号是不合法的 不能发送 所以直接返回
    }
    try {
      // 调用action
      await dispatch(sendCode(mobile)) // 发送验证码
      Toast.show({
        content: "验证码已发送",
      })
      // 开始计时
      setTimeLeft(60) // 开始计时  倒计时
      // 开启倒计时

      timeRef.current = window.setInterval(() => {
        setTimeLeft((count) => count - 1) // 设置当前计时一次比一次小
      }, 1000) // 将定时器标识赋值ref属性
    } catch (error) {
      // 需要将error的对象 断言成 axios的错误
      const e = error as AxiosError<{ message: string }>
      // 当失败时进行提示
      Toast.show({
        content: e.response?.data.message,
      })
    }
  }
  // 使用useEffect监听timeLeft的变化
  useEffect(() => {
    console.log("此时发生变化", timeLeft)
    if (timeLeft === 0) {
      // 等于0意味着 倒计时结束了 清除定时器  需要一个属性或者对象能够记住之前的定时器的标识
      window.clearInterval(timeRef.current)
    }
    // 当上次的更新结束之后 会执行 return的函数
    // return () => {}
  }, [timeLeft])
  // 此时
  useEffect(() => {
    return () => {
      // 回调函数会在该组件卸载时执行 清理定时器 因为组件已经不再了 定时器不需要了

      window.clearInterval(timeRef.current)
    }
  }, [])
  return (
    <div className={styles.root}>
      <NavBar></NavBar>

      <div className="login-form">
        <h2 className="title">账号登录</h2>
        {/* 改变表单校验的方式 vue trigger */}
        <Form form={form} onFinish={onFinish}>
          {/* 需要给Form.Item添加rules属性 */}
          {/* 手机号必填 校验手机号格式 */}
          <Form.Item
            name="mobile"
            validateTrigger="onBlur"
            rules={[
              {
                required: true,
                message: "请输入手机号",
              },
              {
                pattern: /^1[3-9]\d{9}$/, // 正则表达式校验手机号格式 1开头 3-9  9个 数字
                message: "手机号格式不正确",
              },
            ]}
            className="login-item"
          >
            <Input
              ref={mobileRef}
              placeholder="请输入手机号"
              autoComplete="off"
              maxLength={11}
            />
          </Form.Item>

          <Form.Item
            className="login-item"
            name="code"
            validateTrigger="onBlur"
            rules={[
              { required: true, message: "验证码不能为空" },
              {
                pattern: /^\d{6}$/,
                message: "验证码格式不正确",
              },
            ]}
            extra={
              <span
                className="code-extra"
                onClick={timeLeft === 0 ? onSendCode : undefined}
              >
                {timeLeft === 0 ? "发送验证码" : `${timeLeft}秒后发送`}
              </span>
            }
          >
            <Input
              placeholder="请输入验证码"
              autoComplete="off"
              maxLength={6}
            />
          </Form.Item>

          {/* noStyle 表示不提供 Form.Item 自带的样式 */}
          {/* shouldUpdate表示其他任意表单的更新 都会导致该form-item内容的重新渲染  */}
          <Form.Item noStyle shouldUpdate>
            {/* {() => <div>{Math.random()}</div>} */}
            {/* 因为按钮在表单容器中 点击按钮就会触发form表单的提交事件 */}
            {/* disabled应该是动态变量  根据当前的表单校验结果以及用户是否输入过 */}
            {() => {
              // 得到当前是否需要将按钮禁用
              // 1.校验没有通过 2.用户没有触摸过 检测errors的长度是否为0
              // 没有输入的时候 errors也为空数组 或者 用户从来没有输入过
              const disabed =
                form.getFieldsError().filter((item) => item.errors.length > 0)
                  .length > 0 || !form.isFieldsTouched(true)
              // console.log(form.getFieldsError())
              return (
                <Button
                  block
                  type="submit"
                  color="primary"
                  className="login-submit"
                  disabled={disabed}
                >
                  登 录
                </Button>
              )
            }}
          </Form.Item>
        </Form>
      </div>
    </div>
  )
}

export default Login
